﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Entity;
using System.Collections.Generic;
using RobotMapper;
using System.Threading.Tasks;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;

namespace Test
{
    [TestClass]
    public class 动态编译测试
    {
        [TestMethod]
        public void TestMethod1()
        {
            //string code = 
            //    "using System; " +
            //              "using System.IO; " +
            //              "public class MyClass{ " +
            //              "   public static void PrintConsole(string message){ " +
            //              "       Console.WriteLine(message); " +
            //              "   } " +
            //              "} ";

            //获取类框架
            string className = GetClassName("MapperAll");
            Console.WriteLine("类框架：" + className);

            //获取方法框架
            var methodName = GetMethodName(typeof(Entity.User), typeof(DTO.User), "HAHA");
            Console.WriteLine("方法框架：" + methodName);

            //为方法补充实现
            var methodContent = GetRealization((typeof(DTO.User)));
            var method = methodName.Replace("{Realization}", methodContent);
            Console.WriteLine("方法体:{0}", method);

            //方法组装到类中
            string fullClass = className.Replace("{Method}", method);
            Console.WriteLine("全部框架：" + fullClass);

            var methodInfo = GetInvokeMethod(fullClass);

            for (int i = 1; i <= 1000000; i++)
            {
                var user = TestHelper.创建扁平化User();
                var res = methodInfo.Item2.Invoke(methodInfo.Item1, new object[] { user });
            }
        }

        //获取类框架
        public string GetClassName(string className)
        {
            var code =
                "public class " + className +
                "{" +
                "{Method}" +
                "}";
            return code;
        }

        //获取方法框架
        public string GetMethodName(Type sourceType, Type targetType, string methodName)
        {
            string sourceTypeFullName = sourceType.FullName;
            string targetTypeFullName = targetType.FullName;
            string code =
                "public " + targetTypeFullName + " " + methodName + "(" + sourceTypeFullName + " param" + ")" +
                "{" +
                "{Realization}" +
                "}";
            return code;
        }

        //获取实现
        public string GetRealization(Type targetType)
        {
            string targetTypeFullName = targetType.FullName;
            string code =
                "var newObj=new " + targetTypeFullName + "()" + ";" +
                "newObj.Code" + "=" + "param.Code" + ";" +
                "return newObj;";
            return code;
        }

        public Tuple<object, MethodInfo> GetInvokeMethod(string code)
        {
            CSharpCodeProvider codeProvider = new CSharpCodeProvider();
            CompilerParameters compParameters = new CompilerParameters();
            compParameters.ReferencedAssemblies.Add("Entity.dll");
            compParameters.ReferencedAssemblies.Add("DTO.dll");
            compParameters.GenerateInMemory = true;

            CompilerResults res = codeProvider.CompileAssemblyFromSource(compParameters, code);
            object myClass = res.CompiledAssembly.CreateInstance("MapperAll");
            var method = myClass.GetType().GetMethod("HAHA");
            return new Tuple<object, MethodInfo>(myClass, method);
        }

        //将EntityUser转化为DTOUser
        public object GetUser(Entity.User user)
        {
            DTO.User newUser = new DTO.User();
            newUser.Code = user.Code;
            newUser.Department = user.Department;
            newUser.Id = user.Id;
            return newUser;
        }
    }
}
